/* eslint-disable no-unused-expressions */
/*
 * @Author: AskMeWhy
 * @Date:   2020-05-07 17:47:53
 * @Last Modified by: AskMeWhy
 * @Last Modified time: 2021-01-08 11:44:28
 */
import { merge, isObject } from "../utils/index";

const basicMixins = {
    $emit(...args) {
        this.triggerEvent(...args);
    },
    set(data, callback, isSync = false) {
        return new Promise(resolve => {
            if (typeof callback === "boolean" && callback) {
                this.setData(data, () => {
                    resolve();
                });
            } else if (isSync) {
                this.setData(data, () => {
                    callback && callback();
                    resolve();
                });
            } else {
                this.setData(data, callback);
                resolve();
            }
        });
    },
    getRect(selector, all) {
        return new Promise((resolve, reject) => {
            wx.createSelectorQuery()
                .in(this)
                [
                    // eslint-disable-next-line no-unexpected-multiline
                    all ? "selectAll" : "select"
                ](selector)
                .boundingClientRect(rect => {
                    if (all && Array.isArray(rect) && rect.length) {
                        resolve(rect);
                        return;
                    }
                    if (!all && rect) {
                        resolve(rect);
                        return;
                    }
                    reject(rect);
                })
                .exec();
        });
    },
    getFields(selector, data, all) {
        return new Promise((resolve, reject) => {
            wx.createSelectorQuery()
                .in(this)
                [
                    // eslint-disable-next-line no-unexpected-multiline
                    all ? "selectAll" : "select"
                ](selector)
                .fields(data, rect => {
                    if (all && Array.isArray(rect) && rect.length) {
                        resolve(rect);
                        return;
                    }
                    if (!all && rect) {
                        resolve(rect);
                        return;
                    }
                    reject(rect);
                })
                .exec();
        });
    },
    askNextTick(callback) {
        return new Promise(function (resolve) {
            // return wx.nextTick(resolve);
            return setTimeout(() => {
                callback && callback();
                resolve();
            }, 1000 / 30);
        });
    },
    _getOnlyKey(list, keyTag = "_key") {
        const key = Math.random();
        const _index = list.findIndex(item => item[keyTag] === key);
        if (_index === -1) {
            return key;
        } else {
            return this._getOnlyKey();
        }
    },
    noop() {},
};
const baseOption = {
    data: {},
};
const basicBehavior = Behavior({
    ...baseOption,
    methods: {
        ...basicMixins
    },
});

const pageDefaultMethod = [
    "onLoad",
    "onShow",
    "onReady",
    "onHide",
    "onUnload",
    "onPullDownRefresh",
    "onReachBottom",
    "onShareAppMessage",
    "onPageScroll",
    "onResize",
    "onTabItemTap",
];
const handleMixins = option => {
    if (!option.mixins || !Array.isArray(option.mixins)) {
        return option;
    }
    const mixins = option.mixins;
    delete option.mixins;
    mixins.forEach(curMixin => {
        Object.keys(curMixin).forEach(key => {
            if (pageDefaultMethod.includes(key)) {
                const optionMethod = option[key];
                option[key] = function (...payLoad) {
                    curMixin[key].apply(this, payLoad);
                    return optionMethod && optionMethod.apply(this, payLoad);
                };
            } else if (isObject(curMixin[key])) {
                option[key] = merge(true, option[key], curMixin[key]);
            } else {
                option[key] = option[key] ? option[key] : curMixin[key];
            }
        });
    });

    return option;
};

export { handleMixins, basicMixins, basicBehavior };
